package com.puboot.fileservice.impl;

import com.puboot.fileentity.FileNode;
import com.puboot.fileentity.SearchLib;
import com.puboot.fileservice.FileEsHighLevelService;
import com.puboot.fileservice.FileService;
import com.puboot.fileservice.model.ResolveCallBackMsg;
import com.puboot.fileservice.task.FileResolveTaskCallBack;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Created by kk on 2020/7/31.
 */
@Service
@Slf4j
public class FileHighLevelServiceImpl implements FileService {

    @Autowired
    private RestHighLevelClient esClient;

    @Autowired
    private FileEsHighLevelService fileEsHighLevelService;

    @Override
    public List<Map> queryFileFromES(String esIndex, String keyword, String path, Integer esFrom, Integer esSize) {
        SearchRequest searchRequest = new SearchRequest(esIndex);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        String highLightField = "content";
        QueryBuilder matchQueryc = QueryBuilders.matchPhraseQuery("content", keyword);
        QueryBuilder matchQueryn = QueryBuilders.matchPhraseQuery("name", keyword);
        QueryBuilder matchQueryPath = QueryBuilders.matchPhraseQuery("path", path);
        BoolQueryBuilder boolQueryMust1 = QueryBuilders.boolQuery();
        if (StringUtils.isNotEmpty(keyword)) {
            boolQueryMust1.should(matchQueryc);
            boolQueryMust1.should(matchQueryn);
        }
        BoolQueryBuilder boolQueryMust2 = QueryBuilders.boolQuery();
        if (StringUtils.isNotEmpty(path)) {
            boolQueryMust2.must(matchQueryPath);
        }
        BoolQueryBuilder boolQueryMust = QueryBuilders.boolQuery();
        boolQueryMust.must(boolQueryMust1).must(boolQueryMust2);

        //数据过滤
        sourceBuilder.query(boolQueryMust);
        //分页
        sourceBuilder.from(esFrom);
        sourceBuilder.size(esSize);

        HighlightBuilder hiBuilder = new HighlightBuilder();
        hiBuilder.preTags("<span class='high_light'>");
        hiBuilder.postTags("</span>");
        hiBuilder.field(highLightField);
        hiBuilder.field("name");
        //高亮
        sourceBuilder.highlighter(hiBuilder);
        //执行搜索
        searchRequest.source(sourceBuilder);


        // 搜索数据
//        SearchResponse response = esClient.search(esIndex)
//                .setQuery(boolQueryMust).setFrom(esFrom).setSize(esSize)
//                .highlighter(hiBuilder)
//                .execute().actionGet();

        SearchResponse response = null;
        try {
            response = esClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("ES 全文检索异常",e);
        }
        //获取查询结果集
        SearchHits searchHits = response.getHits();
        log.info("共搜到:" + searchHits.getTotalHits() + "条结果!");
        List<Map> list = new ArrayList();
        for (SearchHit searchHit : searchHits.getHits()) {
            Map jfileMap = searchHit.getSourceAsMap();
            HighlightField highlightFieldName =  searchHit.getHighlightFields().get("name");
            HighlightField highlightFieldContent = searchHit.getHighlightFields().get(highLightField);

            Text[] nameText = highlightFieldName == null ? new Text[]{} : highlightFieldName.getFragments();
            StringBuffer name = new StringBuffer();
            for (Text str : nameText) {
                name.append(str);
            }

            Text[] text = highlightFieldContent == null ? new Text[]{} : highlightFieldContent.getFragments();
            StringBuffer content = new StringBuffer();
            for (Text str : text) {
                content.append(str);
            }



            String textContent = content.toString();
            jfileMap.put("text", textContent);
            jfileMap.put("name",name.toString());
            jfileMap.put("rid", searchHit.getId());
            jfileMap.put("totaRecords",searchHits.getTotalHits());
            list.add(jfileMap);
        }
        return list;
    }

    @Override
    public void resolveAllFile(SearchLib searchLib, FileResolveTaskCallBack fileResolveTaskCallBack) throws IOException {
        /*删除索引*/
        ResolveCallBackMsg msg = new ResolveCallBackMsg();
        msg.setFinish(false);
        msg.setLevel("info");
        try {
            deleteIndex(searchLib);
            msg.setMsg("删除es索引成功");
            fileResolveTaskCallBack.doCallBack(msg);
        } catch (Exception e) {
            msg.setLevel("error");
            msg.setMsg("删除es索引失败");
            fileResolveTaskCallBack.doCallBack(msg);
        }
        try {
            msg.setMsg("创建es索引成功");
            fileEsHighLevelService.createFileIndex(searchLib);
            fileResolveTaskCallBack.doCallBack(msg);
        } catch (Exception e) {
            msg.setLevel("error");
            log.error("创建es索引失败", e.fillInStackTrace());
            msg.setMsg("创建es索引失败,请检查是否es是否启动。");
            msg.setFinish(true);
            fileResolveTaskCallBack.doCallBack(msg);
            return;
        }
        try {
            msg.setMsg("刷新缓存成功！");
            flushAllRedis();
            resolveFliesList2TreeNode();
            fileResolveTaskCallBack.doCallBack(msg);
        } catch (Exception e) {
            log.error("刷新缓存失败", e.fillInStackTrace());
            msg.setFinish(true);
            msg.setLevel("error");
            msg.setMsg("刷新缓存失败，请检查redis是否启动！");
            fileResolveTaskCallBack.doCallBack(msg);
            return;
        }

        msg.setMsg("请稍后即将开始处理文件...");
        fileResolveTaskCallBack.doCallBack(msg);
        resolveFileByPath(searchLib, searchLib.getFileSourceDir(), fileResolveTaskCallBack);

    }

    @Override
    public void resolveFileByPath(SearchLib searchLib, String path, FileResolveTaskCallBack fileResolveTaskCallBack) throws IOException {

    }

    @Override
    public String deleteIndex(SearchLib searchLib) {
        DeleteIndexRequest  deleteRequest = new DeleteIndexRequest(searchLib.getEsIndex());
        try {
            AcknowledgedResponse delete = esClient.indices().delete(deleteRequest, RequestOptions.DEFAULT);
            //如果没删除成功，抛出异常
            if (!delete.isAcknowledged()) {
                log.error("删除ES索引失败");
                return "fail";
             }
        } catch (IOException e) {
           log.error("删除ES索引异常",e);
        }
        return "success";
    }

    @Override
    public String flushAllRedis() {
        return null;
    }

    @Override
    public Object readFile2FormatTree(String key) {
        return null;
    }

    @Override
    public boolean findFileByViewPath(SearchLib searchLib, String viewPath) {
        return false;
    }

    @Override
    public void sendToDesktop(SearchLib searchLib, String path, String userid) {

    }

    @Override
    public void removeFromDesktop(SearchLib searchLib, String path, String userid) {

    }

    @Override
    public List<FileNode> getMyDesktop(String userid) {
        return null;
    }

    @Override
    public void clearDesktop(String userid) {

    }

    @Override
    public void resolveFliesList2TreeNode() {

    }

    @Override
    public void addNode2cache(FileNode fileNode, SearchLib searchLib) {

    }
}
